package com.surprise.common.util;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.log4j.Logger;

/**
 * 字符串处理工具类
 * @author zhangceven
 * 
 */
public class StringUtils {
	
	private static Logger logger = Logger.getLogger(StringUtils.class);
	
	/**
	 * 邮箱正则
	 */
	private static String EMAIL_REGEX = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)+[a-zA-Z]{2,}$";
	
	/**
	 * 手机号正则:支持170虚拟运营商号段
	 */
	private static String MOBILE_REGEX = "^((13[0-9])|(15[^4,\\D])|(14[57])|(17[0])|(17[7])|(18[0,0-9]))\\d{8}$";
	
	/**
	 * 固定电话正则
	 */
	private static String TELEPHONE_REGEX = "^(0\\d{2}-\\d{8}(-\\d{1,4})?)|(0\\d{3}-\\d{7,8}(-\\d{1,4})?)$";
	
	/**
	 * 传真正则
	 */
	private static String FAX_REGEX = "^(0\\d{2}-\\d{8}(-\\d{1,4})?)|(0\\d{3}-\\d{7,8}(-\\d{1,4})?)$";
	
	/**
	 * QQ正则
	 */
	private static String QQ_REGEX = "[1-9][0-9]{5,11}";
	
	 /**
     * 正则表达式：验证身份证
     */
    public static String ID_CARD_REGEX = "(^\\d{18}$)|(^\\d{15}$)";
    
    /**
     * 正则表达式：验证IP地址
     */
    public static String IP_ADDR_REGEX = "(25[0-5]|2[0-4]\\d|[0-1]\\d{2}|[1-9]?\\d)";
    
    /**
     * 正则表达式：验证密码
     */
    public static String PASSWORD_REGEX = "^[a-zA-Z0-9]{6,16}$";
	
	/**
	 * 判断传入字符串是否为空
	 * @param value	传入的字符串
	 * @return
	 */
	public static boolean isEmpty(CharSequence value){
		if(value == null || value.length() == 0){
			return true;
		}
		return false;
	}
	
	/**
	 * 判断传入字符串是否不为空
	 * @param value	传入的字符串
	 * @return
	 */
	public static boolean isNotEmpty(CharSequence value){
		if(value != null && value.length() > 0){
			return true;
		}
		return false;
	}
	
	/**
	 * 将传入字符串截取并转为数字
	 * @param value 传入的字符串
	 * @param start	开始截取字符串
	 * @param to	结束截取字符串
	 * @return
	 */
	public static Integer subStringToInteger(String value,String start,String to){
		return stringToInteger(subString(value, start, to));
	}
	
	/**
	 * 将传入字符串截取并返回
	 * @param value	传入字符串
	 * @param start	开始截取的字符串
	 * @param to	结束截取的字符串
	 * @return
	 */
	public static String subString(String value,String start,String to){
		int indexStart = start == null ? 0 : value.indexOf(start);
		int indexTo = to == null ? value.length() : value.indexOf(to);
		if(value.isEmpty()){
			logger.warn("subString(String value,String start,String to);The incoming values of '" + value + "' cannot be empty!");
			return null;
		}
		if(indexStart < 0 || indexTo < 0 || indexStart > indexTo){
			logger.error("Indexes can not less than zero or start index can not greater than ending index");
			return null;
		}
		
		if(start != null){
			indexStart += start.length();
		}
		
		return value.substring(indexStart,indexTo);
	}
	
	/**
	 * 将传入字符串型数字转换成整形数字
	 * @param value
	 * @return
	 */
	public static Integer stringToInteger(String value){
		if(isEmpty(value)){
			return null;
		}
		value = value.trim();
		try {
			return Integer.parseInt(value);
		} catch (Exception e) {
			logger.error("The incoming string of" + value + " is not a number");
			e.printStackTrace();
			return null;
		}
	}
	
	/**
	 * 判断传入字符串是否为邮箱
	 * @param value 传入邮箱
	 * @return
	 */
	public static boolean isEmail(String value){
		boolean flag = false;
		try {
			String regex = EMAIL_REGEX;
			Pattern pattern = Pattern.compile(regex );
			Matcher matcher = pattern.matcher(value);
			flag = matcher.matches();
			
		} catch (Exception e) {
			logger.error("Please enter the correct email format");
			e.printStackTrace();
		}
		
		return flag;
	}
	
	/**
	 * 判断传入字符串是否为手机号码
	 * 支持虚拟运营商170号段
	 * @param value 传入手机号
	 * @return
	 */
	public static boolean isMobileNum(String value){
		boolean flag = false;
		try {
			String regex = MOBILE_REGEX;
			Pattern pattern = Pattern.compile(regex );
			Matcher matcher = pattern.matcher(value);
			flag = matcher.matches();
			
		} catch (Exception e) {
			logger.error("Please enter the correct phone number");
			e.printStackTrace();
		}
		
		return flag;
	}
	
	/**
	 * 判断传入的字符串是否为固定电话
	 * @param value 传入固话
	 * @return
	 */
	public static boolean isTelephoneNum(String value){
		boolean flag = false;
		try {
			String regex = TELEPHONE_REGEX;
			Pattern pattern = Pattern.compile(regex );
			Matcher matcher = pattern.matcher(value);
			flag = matcher.matches();
			
		} catch (Exception e) {
			logger.error("Please enter the correct phone number");
			e.printStackTrace();
		}
		
		return flag;
	}
	
	/**
	 * 判断传入的字符串是否为传真号码
	 * @param value 传入传真号码
	 * @return
	 */
	public static boolean isFaxNum(String value){
		boolean flag = false;
		try {
			String regex = FAX_REGEX;
			Pattern pattern = Pattern.compile(regex );
			Matcher matcher = pattern.matcher(value);
			flag = matcher.matches();
			
		} catch (Exception e) {
			logger.error("Please enter the correct fax number");
			e.printStackTrace();
		}
		
		return flag;
	}
	
	/**
	 * 判断传入的字符串是否为QQ号码
	 * @param value 传入QQ
	 * @return
	 */
	public static boolean isQQNum(String value){
		boolean flag = false;
		try {
			String regex = QQ_REGEX;
			Pattern pattern = Pattern.compile(regex );
			Matcher matcher = pattern.matcher(value);
			flag = matcher.matches();
			
		} catch (Exception e) {
			logger.error("Please enter the correct QQ number");
			e.printStackTrace();
		}
		
		return flag;
	}
	
	/**
	 * 获取传入手机号码归属运营商
	 * chinaUnicom	联通
	 * chinaMobile	移动
	 * chinaTelecom 电信
	 * VNO			虚拟运营商
	 * @param value
	 * @return
	 */
	public static String getMobileType(String value){
		
		if (value.startsWith("0") || value.startsWith("+860")) {  
	        value = value.substring(value.indexOf("0") + 1, value.length());  
	    }  
	    
		List<String> chinaUnicomNumList = Arrays.asList(new String[] { "130", "131", "132", "145","155", "156", "175", "176", "185", "186"});  
	    
	    List<String> chinaMobileNumList = Arrays.asList(new String[] { "134", "135", "136", "137", "138", "139", "147","150", "151", "152", "157", 
	    		"158", "159", "182","187", "188" });  
	    
	    List<String> chinaTelecomNumList = Arrays.asList(new String[]{"133", "153", "180", "181", "189", "177", "173", "149"});
	    
	    List<String> mvnoNumList = Arrays.asList(new String[]{"170", "171"});
	    
	    boolean bolChinaUnicom = (chinaUnicomNumList.contains(value.substring(0, 3)));  
	    
	    if (bolChinaUnicom) {
	    	return "chinaUnicom";//联通   
	    }
	    
	    boolean bolChinaMobile = (chinaMobileNumList.contains(value.substring(0, 3)));  
	    
	    
	    if (bolChinaMobile) {
	    	return "chinaMobile"; //移动   
	    }
	    
	    boolean bolChinaTelecom = (chinaTelecomNumList.contains(value.substring(0, 3)));
	    
	    if(bolChinaTelecom){
	    	return "chinaTelecom";
	    }
	    
	    boolean bolMvno = (mvnoNumList.contains(value.substring(0, 3)));
	    
	    if(bolMvno){
	    	return "VNO";
	    }
	    
		return null;
	}
	
	/**
	 *  获取传入固定电话号码归属运营商(暂未完善)
	 * chinaUnicom	联通
	 * chinaMobile	移动
	 * chinaTelecom 电信
	 * @param value
	 * @return
	 */
	public static String getTelephoneType(String value){
		
		
		
		
		
		return value;
	}
	
	/**
	 * 判断传入的字符串是否为身份证号码
	 * @param value 传入身份证
	 * @return
	 */
	public static boolean isIDCARD(String value){
		boolean flag = false;
		try {
			String regex = ID_CARD_REGEX;
			Pattern pattern = Pattern.compile(regex);
			Matcher matcher = pattern.matcher(value);
			flag = matcher.matches();
			
		} catch (Exception e) {
			logger.error("Please enter the correct ID_CARD number");
			e.printStackTrace();
		}
		
		return flag;
	}
	
	/**
	 * 判断传入的字符串是否为密码
	 * @param value 传入密码
	 * @return
	 */
	public static boolean isPassword(String value){
		boolean flag = false;
		try {
			String regex = PASSWORD_REGEX;
			Pattern pattern = Pattern.compile(regex);
			Matcher matcher = pattern.matcher(value);
			flag = matcher.matches();
			
		} catch (Exception e) {
			logger.error("Please enter the correct password");
			e.printStackTrace();
		}
		
		return flag;
	}
	
	/**
	 * MD5加密字符串
	 * @param source
	 * @return
	 */
	public static String md5Encrypt(String source) {  
        
	    StringBuffer sb = new StringBuffer(32);  
	          
	    try {  
	        MessageDigest md    = MessageDigest.getInstance("MD5");  
	        byte[] array        = md.digest(source.getBytes("utf-8"));  
	              
	        for (int i = 0; i < array.length; i++) {  
	            sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).toUpperCase().substring(1, 3));  
	        }  
	    } catch (Exception e) {  
	        logger.error("Can not encode the string '" + source + "' to MD5!", e);  
	        return null;  
	    }  
	          
	    return sb.toString();  
	}
	
	
	/**
	 * MD5加密(带盐)
	 * @param source
	 * @param salt
	 * @return
	 */
	public static String md5EncryptWithSalt(String source, String salt){
		
		StringBuffer sb = new StringBuffer(32);  
        
	    try {  
	        // 第一次MD5加密
	    	MessageDigest md    = MessageDigest.getInstance("MD5");  
	        byte[] array        = md.digest(source.getBytes("utf-8"));  
	              
	        for (int i = 0; i < array.length; i++) {  
	            sb.append(Integer.toHexString((array[i] & 0xFF) | 0x100).toUpperCase().substring(1, 3));  
	        } 
	        
	        // 加盐加密
	        sb = sb.append(salt);
	        
	        return DigestUtils.md5Hex(sb.toString());
	        
	    } catch (Exception e) {  
	        logger.error("Can not encode the string '" + source + "' to MD5!", e);  
	    }
	    return null;  
	}
	
	/**
	 * MD5加密
	 * @param str
	 * @return
	 */
	public static String getMD5(String str) {
		MessageDigest messageDigest = null;
		try {
			messageDigest = MessageDigest.getInstance("MD5");
			messageDigest.reset();
			messageDigest.update(str.getBytes("UTF-8"));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			
		}
		byte[] byteArray = messageDigest.digest();

		StringBuffer md5StrBuff = new StringBuffer();

		for (int i = 0; i < byteArray.length; i++) {
			if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
				md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
			else
				md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
		}

		return md5StrBuff.toString();
	}
	
	public static String getIpAddress(HttpServletRequest request) {  
		String ip = request.getHeader("x-forwarded-for");  
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			ip = request.getHeader("Proxy-Client-IP");  
		}  
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			ip = request.getHeader("WL-Proxy-Client-IP");  
		}  
		if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
			ip = request.getRemoteAddr();  
		}  
		return ip;  
	}
	
	/**
	 * 获取时间字符串
	 * @param date 时间
	 * @param pattern 规则: yyyy-MM-dd HH:mm:ss
	 * @return
	 */
	public static String getDateTime(Date date,String pattern){
		
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		
		String time = sdf.format(date);
		
		return time;
	}
	
	
}
